package com.runa.monitor.platinterface.netservice.equipment;

import com.runa.monitor.comm.dto.Archive;
import com.runa.monitor.comm.dto.Node;
import com.runa.monitor.comm.dto.NodeEquModel;
import com.runa.monitor.comm.dto.NodeEquModel.NodeEquType;
import com.runa.monitor.platinterface.backwork.function.TaskFunction;
import com.runa.monitor.platinterface.netservice.connect.commstatus.CommStatus;
import com.runa.protocol.dto.IRequestData;
import com.runa.protocol.util.ByteUtil;
import com.runa.rccprotocol.dto.AffirmDeny;
import com.runa.rccprotocol.dto.ConcentratorRequestData;
import com.runa.rccprotocol.dto.ConcentratorRequestDataProxy;
import com.runa.rccprotocol.dto.en.EnMeterRequestData;
import com.runa.rccprotocol.dto.equdata.EquData;
import com.runa.rccprotocol.dto.lanjier.FmuLanJiErRequestData;
import com.runa.rccprotocol.dto.lichuang.LiChuangEquRequestData;
import com.runa.rccprotocol.dto.param.ExtendParam;
import com.runa.rccprotocol.dto.runa.RunaRCRequestData;
import com.runa.rccprotocol.dto.zhongrun.ZhongRunEquRequestData;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author diandian
 * @Date 2022/5/7 11:03
 */
@Slf4j
public class LanJiErDriver extends NetEqu<String> {
    private FmuLanJiErRequestData fmu_requestData;
    //兰吉尔
    private EnMeterRequestData enRequestData;
    //力创
    private LiChuangEquRequestData liChuangRequestData;
    //瑞纳
    private RunaRCRequestData ruiNaRequestData = null;
    //中润
    private ZhongRunEquRequestData zhongRunRequestData = null;

    public LanJiErDriver(String serial, Integer timeout) {
        super(serial, timeout);
        this.fmu_requestData = new FmuLanJiErRequestData(serial, null);
        this.enRequestData = new EnMeterRequestData(serial);
        this.liChuangRequestData = new LiChuangEquRequestData(serial);
        this.ruiNaRequestData = new RunaRCRequestData();
        this.zhongRunRequestData = new ZhongRunEquRequestData(serial);
    }

    @Override
    public void readNodeEqu(List<Node> nodeList, TaskFunction function, EquData.EquDataType type) {
        //如果集中器不在线直接触发离线回调
        if (!online()) {
            function.doApply(CommStatus.OffLine, nodeList);
            return;
        }
        switch (type) {
            case METER:
                readHouseMeter(nodeList, function);
                break;
            default:
        }
    }

    private void readHouseMeter(List<Node> hMeters, TaskFunction function) {
        for (Node node : hMeters) {
            String model = node.getModel();
            String serial = node.getSerial();
            fmu_requestData.setPort(node.getPort().byteValue());
            ConcentratorRequestData concentratorRequestData = null;
            if ("兰吉尔LJ户表".equals(model)) {
                readEN_HouseMeter(node, function);
            } else if ("ZRM型".equals(model)) {
                concentratorRequestData = zhongRunRequestData;
                zhongRunRequestData.readHeatMeter(serial);
                readMeter(node, function, concentratorRequestData);
            } else if ("力创LC户表".equals(model)) {
                concentratorRequestData = liChuangRequestData;
                liChuangRequestData.readHeatMeter(serial);
                readMeter(node, function, concentratorRequestData);
            } else if ("RC型".equals(model)) {
                concentratorRequestData = ruiNaRequestData;
                ruiNaRequestData.readHeatMeter(serial);
                readMeter(node, function, concentratorRequestData);
            }
        }
    }

    private void readMeter(Node node, TaskFunction function, ConcentratorRequestData concentratorRequestData) {
        concentratorRequestData.setHaveResult(true);
        fmu_requestData.setRequestData(concentratorRequestData);
        ConcentratorRequestDataProxy dataProxy = new ConcentratorRequestDataProxy(serial(), fmu_requestData);
        dataProxy.setRemain(Collections.singletonList(node));
        super.sendRequest(dataProxy, function);
    }

    private void readEN_HouseMeter(Node node, TaskFunction function) {
        fmu_requestData.setRequestData(enRequestData);
        Boolean initRes = initAndChoose(node.getSerial(), function);
        if (initRes) {
            enRequestData.readHouseMeter();
            ConcentratorRequestDataProxy dataProxy = new ConcentratorRequestDataProxy(serial(), fmu_requestData);
            dataProxy.setRemain(Collections.singletonList(node));
            super.sendRequest(dataProxy, function);
            destroy();
        }
    }

    private Boolean initAndChoose(String serial, TaskFunction function) {
        LanJiErDriver.EnFunction chooseFunc = new LanJiErDriver.EnFunction(function);
        enRequestData.choseHouseMeter(serial);
        ConcentratorRequestDataProxy dataProxy = new ConcentratorRequestDataProxy(serial(), fmu_requestData);
        super.sendRequest(dataProxy, chooseFunc);
        Boolean chooseRes = chooseFunc.waitResult();
        return chooseRes;
    }

    private boolean destroy() {
        LanJiErDriver.EnFunction closeFunc = new LanJiErDriver.EnFunction();
        enRequestData.destroy();
        fmu_requestData.setRequestData(enRequestData);
        ConcentratorRequestDataProxy dataProxy = new ConcentratorRequestDataProxy(serial(), fmu_requestData);
        super.sendRequest(dataProxy, closeFunc);
        Boolean closeRes = closeFunc.waitResult();
        return closeRes;
    }

    @Override
    public void setNodeEquArchive(List<Archive> archives, TaskFunction function) {

    }

    @Override
    public void clearNodeEquArchive(TaskFunction function) {

    }

    @Override
    public void valveOnOffControl(List<Node> valveSerial, boolean ifLock, Integer opening, TaskFunction function) {

    }

//    @Override
//    public void valveTemperatureLock(List<String> valveSerial, boolean ifLock, float temperature, TaskFunction function) {
//
//    }
//
//    @Override
//    public void valveTemperatureLimit(List<String> valveSerial, float up, float down, TaskFunction function) {
//
//    }

    @Override
    public void readNodeRecord(List<Integer> indexes, TaskFunction function) {

    }

    @Override
    public void sentPublicUnitRecord(List<Node> valveSerial, Integer model, Map param, TaskFunction function) {

    }

    @Override
    public void sentPublicUnitModel(List<Node> valveSerial, boolean model, TaskFunction function) {

    }

    @Override
    public void sentExtendParam(ExtendParam param, TaskFunction function) {

    }

    @Override
    public void readPublicUnitRecord(Node valveSerial, Integer model, TaskFunction function) {

    }

    @Override
    public void readPublicUnitAndMeter(Node valveSerial, Node meterSerial, TaskFunction function) {

    }

    private long heartbeatInterval = 0;
    @Override
    public void heartbeatUpdate() {
        heartbeatTimestamp = System.currentTimeMillis();
        if (heartbeatTimestamp != 0) {
            //利用5次心跳的时间再加上10s的延迟误差来计算心跳间隔
            long diff = System.currentTimeMillis() - heartbeatTimestamp;
            heartbeatInterval =  diff < 5 * 60 * 1000 ? 10 * 60 * 1000 : ((diff) * 5);
        }
    }

    @Override
    public boolean heartStop() {
        return heartbeatTimestamp != 0 && heartbeatInterval != 0 && System.currentTimeMillis() - heartbeatTimestamp > heartbeatInterval;
    }

    @Override
    public Node findMeter(String serial, String netId) {
        return null;
    }

    @Override
    public Node findValve(String serial, String netId) {
        return null;
    }

    public static class EnFunction implements TaskFunction<Integer, AffirmDeny, Boolean> {

    private Boolean result = null;

    private TaskFunction function;

    public EnFunction() {
    }

    public EnFunction(TaskFunction function) {
        this.function = function;
    }

    @Override
    public void setStatus(Integer step) {

    }

    @Override
    public void doApply(CommStatus status, AffirmDeny o) {
        result = o != null ? o.getData() : false;
        if (!CommStatus.OK.equals(status) || (o != null && !o.getData())) {
            if (function != null) {
                function.doApply(status, o);
            }
        }
    }

    @Override
    public Boolean waitResult() {
        while (result == null) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {

            }
        }
        return result;
    }

        @Override
        public String getSerial() {
            return null;
        }

        @Override
        public int getPriority() {
            return 0;
        }

    }

    public static void main(String[] args) {
        String fmu = "10460494";
        byte port = 1;
        LanJiErDriver driver = new LanJiErDriver(fmu, 5);
        List<NodeEquModel> models = new ArrayList<>();
        //49 4F 54 40 00 24 00 10 46 04 94 D1 A2 00 15 02 FE FE FE FE 68 20 83 11 02 20 00 11 11 01 03 1F 90 00 13 16 1D 7F D2 72 25 5E
        //49 4F 54 40 00 24 00 10 46 04 94 D1 A2 00 15 01 FE FE FE FE 68 20 83 11 02 20 00 11 11 01 03 1F 90 00 13 16 00 00 00 00 25 5E
        NodeEquModel zhongrun = new NodeEquModel();
        zhongrun.setSerial("20021183");
        zhongrun.setIndex(0);
        zhongrun.setProtocol(0);
        zhongrun.setPort(1);
        zhongrun.setType(NodeEquType.H_METER);
        zhongrun.setModel("ZRM型");
        models.add(zhongrun);

        //49 4F 54 40 00 24 00 10 07 06 27 D1 A2 00 15 01 FE FE FE FE 68 20 16 02 80 21 00 11 11 01 03 1F 90 00 16 16 2E 43 6A 56 25 5E
        //49 4F 54 40 00 24 00 10 46 04 94 D1 A2 00 15 01 FE FE FE FE 68 20 16 02 80 21 00 11 11 01 03 1F 90 00 16 16 00 00 00 00 25 5E
        NodeEquModel runa = new NodeEquModel();
        runa.setSerial("21800216");
        runa.setIndex(0);
        runa.setProtocol(0);
        runa.setPort(1);
        runa.setType(NodeEquType.H_METER);
        runa.setModel("RC型");
        models.add(runa);

        //49 4F 54 40 00 24 00 10 34 02 48 D1 A2 00 15 01 FE FE FE FE 68 20 04 04 66 30 00 59 42 01 03 90 1F 00 74 16 AA 86 56 9E 25 5E
        //49 4F 54 40 00 24 00 10 46 04 94 D1 A2 00 15 01 FE FE FE FE 68 20 04 04 66 30 00 59 42 01 03 90 1F 00 74 16 00 00 00 00 25 5E
        NodeEquModel lichuang = new NodeEquModel();
        lichuang.setSerial("30660404");
        lichuang.setIndex(0);
        lichuang.setProtocol(0);
        lichuang.setPort(1);
        lichuang.setType(NodeEquType.H_METER);
        lichuang.setModel("力创LC户表");
        models.add(lichuang);

        //兰吉尔   49 4F 54 40 00 21 00 10 46 04 94 D1 A2 00 12 01 68 0B 0B 68 53 FD 52 27 14 20 67 FF FF FF FF 60 16 B1 62 29 5D 25 5E
        //        49 4F 54 40 00 21 00 10 46 04 94 D1 A2 00 12 01 68 0B 0B 68 53 FD 52 27 14 20 67 FF FF FF FF 60 16 00 00 00 00 25 5E
        //        49 4F 54 40 00 15 00 10 46 04 94 D1 A2 00 06 01 10 5B FD 58 16 0B 51 DC B1 25 5E
        //        49 4F 54 40 00 15 00 10 46 04 94 D1 A2 00 06 01 10 5B FD 58 16 00 00 00 00 25 5E
        NodeEquModel lanjier = new NodeEquModel();
        lanjier.setSerial("67201427");
        lanjier.setIndex(0);
        lanjier.setProtocol(0);
        lanjier.setPort(1);
        lanjier.setType(NodeEquType.H_METER);
        lanjier.setModel("兰吉尔LJ户表");
        models.add(lanjier);

//        driver.init(models);

//        driver.allRead(newComm TaskFunction() {
//            @Override
//            public void setStatus(Object o) {
//
//            }
//
//            @Override
//            public void doApply(CommStatus status, Object o) {
//
//            }
//
//            @Override
//            public Object getResult() {
//                return null;
//            }
//        }, 0);

    }

    public static void test(IRequestData<byte[]> data) {
        String s = ByteUtil.byteToHexString(data.getData());
        char[] chars = s.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if ((i + 1) % 2 == 0) {
                System.out.print(chars[i] + " ");
            } else {
                System.out.print(chars[i]);
            }
        }
        System.out.println();
    }


}
